//
//  main.c
//  Decimal
//
//  Created by admin on 2019/7/19.
//  Copyright © 2019 猫爷爷的酱醋茶. All rights reserved.
//

#include <stdio.h>
/*
 
 进制：
    一种计数方式，侧重点在于计数的时候逢多少进一。
 
 C语言能识别的进制：
    1）二进制
        逢二进一。
        0 1 10 11 100 101 110 111 1000 ...
        在C语言中表示二进制数，在数字前加0b； 例:int num = 0b1001101;
    2）八进制
        逢八进一。
        0 1 2 3 4 5 6 7 10 11 12 13 14 15 16 17 20 ...
        在C语言中表示八进制数，在数字前加0； 例：int num = 01234;
 

    3）十进制
    4）十六进制
        逢十六进一。
        0 1 2 3 4 5 6 7 8 9 a b c d e f
        在C语言中表示十六进制数，在数字前加0x； 例：int num = 0x167ad;
 
     %d 将整型变量中的数据以十进制的形式输出；
     %o 将整型变量中的数据以八进制的形式输出。
     %x 将整型变量中的数据以十六进制的形式输出。
 
 
 进制的转换
    数码：指的是这个数据的每一为的数字。
    数位：数码在这个数中的位置，从右往左，依次从0开始递增。
    基数：其实就是指的这个数的进制。
    位权：数码乘以（基数的数位次方）
 
  1)十进制转二进制： 除2取余法
    二进制转十进制： 加权法
 
  2)十进制转八进制： 除8取余法
    八进制转十进制： 加权法
 
  3)
    二进制转八进制：
    三合一法则。   100 111 010 101              001 111 010 101 011
                  4   7   2   5                1   7   2   5   3
 
    八进制转二进制：
    一拆三。将八进制数的每一个数码拆分成三位数的二进制。  624 ->  6   2  4
                                                       110 010 100
 4)二进制转十六进制：
    四合一法则。
   十六进制转二进制：
    一拆四。
 
 5)八进制转十六进制
    8—>2->16
 
 内存中的存储单元是由一个个二进制位组成的。每个二进制位只能存储0或者1.
 如果我们使用一个二进制位来存储数据的话，每个二进制位只能表示2个数据。
 科学家为了能够更方便的存储更多的数据，他们加把内存中的8个二进制为分为1组，叫做1个字节，作为存储数据的最小基本单位。
 
 如果要往内存中存储数据的话，就至少要使用1个字节。这个时候，1个字节最多能表示2^8=256种数据。
 变量占用的字节空间一定是连续的。
 每一个字节都有一个独一无二的的内存地址，是一个十六进制的数。因为这样描述数据能短一些。
 
 int    4个字节
 float  4个字节
 double 8个字节
 char   1个字节
 
 在为变量分配内存空间的时候，是从高地址向低地址分配的，分配连续的指定字节数空间。
 存储的时候，数据是以补码的二进制存储的，低位存储在低字节，高位存储在高字节。
 
 字符数据在内存中如何存储？
    字符数据占1个字节，8bit，255.
    字符数据在内存中存储的是这个字符所对应的ASCII码的二进制补码。
    我们可以直接给char变量赋值一个整数，因为char变量本来存储的就是一个整数。也可以使用%d输出char变量的值。
    char变量的最高位表示符号位。
    %c读取字符的时候，先从变量中读取出变量中的整数，再去SASCII码中查找对应的字符，在显示这个字符。
 
 
 变量的地址：
    变量的地址是组成这个变量的低字节地址。
    使用&取地址可以取出变量的地址。
 &变量名; 这个表达式的结果就是这个变量的地址，要打印用%p 占位符。
 
 int num = 10;
 printf("num的地址为%p\n",&num);
 
 
 
 sizeof运算符：
    计算变量、常量在当前系统内存中所占的字节数。
    可能会因为系统版本的不同、编译器的不同，而所占的字节数不同，可以用sizeof()确认。
  使用方法
    a.sizeof(数据类型) 就会返回这个数据类型的变量在内存中占据多少字节。
    b.sizeof(变量名)   就会返回这个变量在内存中占据多少字节。
    c.sizeof(常量) 常量就是直接赋值的数据 例如：sizeof(12.12);  double类型  占8个字节
                                          sizeof(12.12f); float类型   占4个字节
 注意： char类型的变量占1个字节   char a = 'a'; sizeof(a);
       char类型的常量占4个字节  sizeof('a');
 
 
 1. 无论任何数据，在内存中存储的时候都是以二进制的形式存储的。
    int num = 10;
    原码、反码、补码都是二进制，只不过是二进制的不同的表现形式。
 
    数据是以补码的二进制存储的。
    因为计算机中只有加法，没有减法，为了更低成本的计算出结果，所以用补码来存储数据。
 
    3+2；
    3-2；这个减法运算对于计算机而言，它的理解是 3+(-2).
 
    验证：
    使用原码计算：
    3的原码：   00000000 00000000 00000000 00000011
    -2的原码：  10000000 00000000 00000000 00000010
 ---------------------------------------------------
              10000000 00000000 00000000 00000101   结果是1个负数，明显不对
 
    使用反码计算：
    3的反码：   00000000 00000000 00000000 00000011
    -2的反码：  11111111 11111111 11111111 11111101
  ---------------------------------------------------
            1  00000000 00000000 00000000 00000000  舍弃超出的最高位1，结果为0，也不正确
 
 
    使用补码计算：
    3的补码：   00000000 00000000 00000000 00000011
    -2的补码：  11111111 11111111 11111111 11111110
 ---------------------------------------------------
            1 00000000 00000000 00000000 00000001  结果为1.正确。
 
 因为用补码运算是效率最高的。
 
 
 2. 1个int类型的变量，在内存中占据4个字节，32位
    00000000 00000000 00000000 00000000
    在不考虑正负的情况下，1个int类型的变量可以表示接近2^32 = 43e种数据。
 
    为了可以表示正负性，使用最高位来表示这个数的正负性。
    如果最高位为0，那么表示这个数是1个正数；
    如果最高位为1，那么表示这个数是1个负数。
    所以，用来表示数据的只有31位，所以一个int类型的变量 2^31
    最小值：-2147483648 最大值：2147483647
 
 3. 原码：
    最高位表示符号位，剩下的位数，是这个数的绝对值的二进制数。
 
    10的原码：
    00000000 00000000 00000000 00001010
 
    -20的原码：
    10000000 00000000 00000000 00010100
 
 4. 反码：
    正数的反码就是其原码。
    负数的反码就是在其原码的基础上，符号位不变，其他位取反。
 
    10的原码：00000000 00000000 00000000 00001010
    10的反码：00000000 00000000 00000000 00001010
 
    -20的原码：10000000 00000000 00000000 00010100
    -20的反码：11111111 11111111 11111111 11101011
 
 5. 补码
    正数的补码就是其原码。
    负数的反码就是在其反码的基础上+1.
 
    10的原码：00000000 00000000 00000000 00001010
    10的反码：00000000 00000000 00000000 00001010
    10的补码：00000000 00000000 00000000 00001010
 
    -20的原码：10000000 00000000 00000000 00010100
    -20的反码：11111111 11111111 11111111 11101011
    -20的补码：11111111 11111111 11111111 11101100
 
 */

//二进制
void Binary(void);

//八进制
void Octal(void);

int main(int argc, const char * argv[]) {
    
    char a = 'a';
    int num = sizeof(a);
    printf("num = %o\n",num);
    return 0;
}

//八进制
void Octal(void)
{
    int num = 0123;
    //输出是以十进制的方式输出
    printf("num = %d\n",num);
}

//二进制
void Binary(void)
{
    int num = 0b1101101;
    //输出是以十进制的方式输出
    printf("num = %d\n",num);
    
}
